﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            /*
             * Per ogni macchina potrei raggruppare il tempo di lavoro in base alla data di consegna.
             * Non importa che associo il determinato articolo alla determinata giornata. devo solo sapere ore libero.
             * 
             * Itero le varie scadenze.
             * Ognuna deve sapere se ho ore a disposizione oppure sono pieno.
             * 
             */

            var testDate = new DateTime(2012, 3, 28);

            var impegnoOre = new Dictionary<DateTime, double>
                                 {
                                     {testDate.AddDays(-5), 2*8},
                                     {testDate.AddDays(5), 4*8},
                                     {testDate.AddDays(10), 6*8},
                                     {testDate.AddDays(20), 8*8},
                                     {testDate.AddDays(30), 10*8},
                                 };

            var orario = new OrarioDiLavoro();

            //rimanenza di ore da scadenze precedenti.
            var now = testDate;

            // Giorni ritardo -> riferito a data di consegna.
            // Data consegna prevista -> riferito a data attuale.

            Console.WriteLine("Data riferimento : {0}", now.ToShortDateString());
            Console.WriteLine();

            foreach (var d in impegnoOre)
            {
                var dataConsegna = d.Key;

                var oreImpegno = d.Value;

                Console.WriteLine("Scadenza del {0} , ci sono {1} ore di lavoro complessive previste", dataConsegna.ToShortDateString(), oreImpegno);

                var deltaOre = orario.GetOreDisponibili(now, dataConsegna);

                var rimanenzaOre = deltaOre - oreImpegno;

                if (rimanenzaOre > 0) // Disponibilità ore
                {
                    Console.WriteLine("La consegna del {0} ho {1} ore di lavoro disponibili",
                                      dataConsegna.ToShortDateString(), rimanenzaOre);
                }
                else if (rimanenzaOre == 0)
                {
                    Console.WriteLine("La consegna del {0} è puntuale",
                                      dataConsegna.ToShortDateString());
                }
                else // Ritardo
                {
                    var nDataConsegna = orario.GetDataFineLavori(dataConsegna, Math.Abs(rimanenzaOre));

                    Console.WriteLine("La consegna del {0} ho {1} ore di ritardo, consegna prevista il {2}", dataConsegna.ToShortDateString(), Math.Abs(rimanenzaOre), nDataConsegna.ToShortDateString());
                }

                Console.WriteLine();
            }

            Console.ReadKey();

        }

        public class OrarioDiLavoro
        {
            public List<DayOfWeek> Festivi = new List<DayOfWeek> { DayOfWeek.Sunday, DayOfWeek.Saturday };

            public double OreLavGiornaliere = 8;

            public List<int> OrariLavoro = new List<int> { 8, 9, 10, 11, 14, 15, 16, 17 };


            public DateTime GetDataFineLavori(DateTime start, double totaleOreLavoro)
            {
                while (totaleOreLavoro > 0)
                {
                    if (!Festivi.Contains(start.DayOfWeek) && OrariLavoro.Contains(start.Hour))
                        totaleOreLavoro -= 1;

                    start = start.AddHours(1);
                }

                // 
                if (OrariLavoro.Any(i => start.Hour > i))
                {
                    start = start.AddDays(1);
                }

                return start;
            }

            public double GetOreDisponibili(DateTime start, DateTime end)
            {
                var oreDisponibili = 0.0d;

                var inizio = start < end ? start : end;
                var fine = start < end ? end : start;
                var isDateBehind = start >= end;

                // L'ora della data finale deve avere orario settato tipo a 23:59. altrimenti non conta le ore di quel giorno.
                fine = fine.Add(new TimeSpan(23, 59, 00));

                while (inizio < fine)
                {
                    if (!Festivi.Contains(inizio.DayOfWeek) && OrariLavoro.Contains(inizio.Hour))
                    {
                        oreDisponibili += 1;
                    }

                    inizio = inizio.AddHours(1);
                }

                if (isDateBehind)
                    return -oreDisponibili;
                return oreDisponibili;

            }
        }
    }
}


//var rimanenzaOre = 00.0d;

//            DateTime dataIndice = DateTime.Now;

//            var prevOreImpegno = 0.0d;

//            foreach (var d in impegnoOre)
//            {
//                var dataConsegna = d.Key;

//                var oreImpegno = d.Value - prevOreImpegno;

//                var deltaOre = orario.GetOreDisponibili(dataIndice, dataConsegna);

//                rimanenzaOre += deltaOre;

//                /*
//                 * Se ho disponibili 10 ore con 3 ore impegno mi rimane 7 ore disponibili
//                 * se ne ho         -10  ne avro -13 . Ovvero ritardo di 13 ore.
//                 */

//                rimanenzaOre -= oreImpegno;

//                // se scadenza è passata >> ritardo == oreImpegno

//                dataIndice = orario.GetDataFineLavori(dataIndice, oreImpegno);

//                prevOreImpegno = d.Value;

//                if (rimanenzaOre > 0)
//                {
//                    Console.WriteLine("La consegna del {0} ho {1} ore di lavoro disponibili",
//                                      dataConsegna.ToShortDateString(), rimanenzaOre );
//                }
//                else
//                {
//                    Console.WriteLine("La consegna del {0} ho {1} giorni di ritardo, consegna prevista il {2}", dataConsegna.ToShortDateString(), Math.Abs(rimanenzaOre / 8), dataIndice.ToShortDateString());
//                }
//            }

//            Console.ReadKey();